iT邦幫忙

0

【You Don't Know JS: Types & Grammar】Chapter 4-3 筆記

WM 2019-02-26 23:05:401507 瀏覽
  • 分享至 

  • xImage
  •  

寬鬆相等 與 嚴格相等

寬鬆相等(==)允許相等比較中的強制轉型,嚴格相等(===)則不允許強制轉型。

如果比較的是相同型別的值,== 與 === 使用相同的演算法。

若比較的是不同型別的值,應該要確認,是否想要強制轉型。

若想強制轉型,就使用==相等性;若不想,則使用===相等性。

如果被比較的值具有相同的型別,它們就會以同一性(Identity)來比較。42只會等於42,"abc"只會等於"abc"。

少數例外:

  • NaN永遠不等於自己
  • +0 與 -0 相等

比較object(function和array),只有在它們都指向同一個值的參考,才會相等。

使用==相等性來比較,若2邊的型別不同,其中之一(或2者)會進行隱含地強制轉型成相同型別,再進行值的同一性比較。

!=寬鬆不相等,反轉==的比較結果;!==嚴格不相等,反轉===的比較結果。

比較:字串與數字

https://ithelp.ithome.com.tw/upload/images/20190226/201125730aKg2Iiu1m.jpg

a === b會失敗,因為===不允許轉型。

a == b成功,意味著,它們轉型成相同的型別比較,那究竟是42轉"42",還是"42"轉42呢?

以ES5的規格指出,"42"會被強制轉型成number再進行比較。

比較:boolean與其他值

若試著將一個值與true/false做比較,有可能出現陷阱。

https://ithelp.ithome.com.tw/upload/images/20190226/20112573iaPTG0bLAa.jpg

根據ES5的規格,如果其中一方是boolean的話,那就會強制轉型成number做比較。

Example:
https://ithelp.ithome.com.tw/upload/images/20190226/20112573Qr1T11BhtC.jpg

x是true(boolean),所以會強制轉型成1(number),而"42"轉型成42。1 == 42的結果很明顯是flase。

https://ithelp.ithome.com.tw/upload/images/20190226/20112573OcNz69L5sP.jpg

y=false,會變成42 == 0,結果也是flase。

問題來了,"42" == true"42" == false結果都是false,那"42"究竟是什麼?

實事上,"42"的確是truthy,問題是出在相等性比較式,"42"是truthy值,擁有true的行為,但不會被轉型成true,而true會被轉型成1。切記,"42"再怎麼轉型,永遠都不會是true。

所以"42"是truthy或flasy,跟==運算一點關係都沒有。

不管在任何情況下,都不要使用== true== flase

=== true=== flase不會強制轉型,所以不會有這個問題產生。

var a = "42";
//會失敗
if (a == true) {
	// ..
}
//會失敗
if (a === true) {
	// ..
}
//會成功,隱含轉型
if (a) {
	// ..
}
//更好,明確轉型
if (!!a) {
	// ..
}
//一樣會成功
if (Boolean( a )) {
	// ..
}

比較:null與undefined

null與undefined,以==相等性進行比較,會等於彼此,也等於自身,而且不相等於其他值。

var a = null;
var b;

a == b;		// true
a == null;	// true
b == null;	// true

a == false;	// false
b == false;	// false
a == "";	// false
b == "";	// false
a == 0;		// false
b == 0;		// false

null與undefined在==相等性的情況下,彼此的強制轉型是安全的,不會有其他的值導致誤判情形。

善用null與undefined的特性:

var a = doSomething();
if (a == null) {
	// ..
}

以上的情形,只有在doSomething()回傳null或undefined時,if判斷式才會通過,即使是其他的false值也是失敗。

var a = doSomething();
if (a === undefined || a === null) {
	// ..
}

使用===不允許強制轉型的話,處理方式就沒那麼漂亮。

比較:物件與非物件

https://ithelp.ithome.com.tw/upload/images/20190226/20112573LQJHKSi4IC.jpg

array是object,所以[42]會先強制轉型成"42",再轉成42,所以整個運算式會變成42 == 42。

容易引起麻煩的情況

"0" == false;			// true
false == 0;				// true
false == "";			// true
false == [];			// true
"" == 0;				// true
"" == [];				// true
0 == [];				// true

以上的7種情況,都為true,我們來分析這7種情況。

"0" == false,false => 0,"0" => 0
false == 0,false => 0
false == "",false => 0," " => 0
false == [],false => 0,[ ] => 0
"" == 0," " => 0
"" == []," " => 0,[ ] => 0
0 == [],[ ] => 0

瘋狂的例子

[] == ![];             // true
2 == [2];		       // true
"" == [null];	       // true

怎麼會是true呢?

[] == ![]!運算子會先將[]轉型成false,所以實際相等性比較是[] == false

2 == [2],object會先轉基型值,[2] => "2" => 2。

"" == [null],[null] => " " => 0。

安全的隱含強制轉型

請思考 == 相等性,另一邊可能會出現的值。

如果比較的任一邊有 truefalse[ ]" "0,就不要使用 ==

比較項目的圖表,幫助記憶。
https://ithelp.ithome.com.tw/upload/images/20190226/20112573tqTWRs5Iu8.png

來源:https://github.com/dorey/JavaScript-Equality-Table

抽象的關係式比較

若遇到a < b的情況,將2個運算元轉型,若其中一方的結果不是string,那這2個值會強迫轉成number,再進行數值的比較。

var a = [ 42 ];
var b = [ "43" ];

a < b;	// true
b < a;	// false

若2個值都是string,那就會進行字元的詞典順序比較。

var a = [ "42" ];
var b = [ "043" ];

a < b;	// false

"42"會跟"043"逐字元作比較,第一個字元是"4"與"0"的比較,"0"在詞典的順序上小於"4",回傳比較結果是false。

那這個呢?

var a = { b: 42 };
var b = { b: 43 };

a < b;	//false

因為ab都會轉成"[object Object]",所以比較上,沒有誰大誰小的問題。

var a = { b: 42 };
var b = { b: 43 };

a < b;	// false
a == b;	// false
a > b;	// false

a <= b;	// true
a >= b;	// true

比較奇怪的是a == b,既然都是"[object Object]",應該要一樣才對啊,各位不要被剛剛的a < b範例誤導了。2個物件的比較,比的是「是否為同一個參考」。

依據規格,a <= b,會先估算b < a的結果(false),再否定其結果,所以a <= b會是true。

<=字面上的意思是「小於或等於」,但更精確的說法應該是「不大於」。所以a <= b被解讀為!(a > b)再視為!(b < a)!false等同於true

a >= b先被視為b <= a,再解讀為!(b > a),再一次視為!(a < b)!false等同於true

參考來源:
https://ithelp.ithome.com.tw/upload/images/20190221/201125739FY75WdXxA.jpg

此為You Don't Know JS系列的筆記。


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言